﻿// Copyright (c) Inossem. All rights reserved.
// Licensed under the LGPL-3.0 license. See LICENSE file in the project root for full license information.
using DWF.Common.Activities.Contract;
using DWF.Studio.RemoteCtrls.Custom;
using DWF.Studio.RemoteCtrls.Models;
using DWF.Studio.RemoteCtrls.Services;
using Microsoft.Activities.Extensions;
using Microsoft.Activities.Extensions.Statements;
using Microsoft.CSharp.Activities;
using System;
using System.Activities;
using System.Activities.Core.Presentation;
using System.Activities.Debugger;
using System.Activities.Expressions;
using System.Activities.Presentation;
using System.Activities.Presentation.Debug;
using System.Activities.Presentation.Hosting;
using System.Activities.Presentation.Model;
using System.Activities.Presentation.Services;
using System.Activities.Presentation.Toolbox;
using System.Activities.Presentation.View;
using System.Activities.Presentation.ViewState;
using System.Activities.Statements;
using System.Activities.Tracking;
using System.Activities.Validation;
using System.Activities.XamlIntegration;
using System.AddIn.Contract;
using System.AddIn.Pipeline;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace DWF.Studio.RemoteCtrls.Proxy
{
    /// <summary>
    /// 活动设计器代理
    /// </summary>
    public class ActivityDesignerProxy : MarshalByRefProxyBase
    {
        /// <summary>
        /// 设计模型改变
        /// </summary>
        public Action<EventArgs> DesignModelChanged;
        /// <summary>
        /// 自变量改变
        /// </summary>
        public Action<ArgumentEventArgs> PropertyModelChanged;

        internal static EventHandler<ModelChangedEventArgs> ModelChanged;

        public Action<BreakpointEventArgs> BreakpointChanged;
        /// <summary>
        /// 设计器
        /// </summary>
        private WorkflowDesigner _workflowDesigner = null;

        /// <summary>
        /// 工程目录
        /// </summary>
        private string _projectDirectory = null;

        /// <summary>
        /// 活动通知
        /// </summary>
        public Action<string, string> ActivityNotice = null;

        private string _workflowFilePath = null;

        private static IExpressionEditorService _expressionEditorService;

        /// <summary>
        /// 硬编码：“注释掉”活动 名称空间
        /// </summary>
        private const string CommentOutActivityTypeName = "DWF.Activities.WorkFlow.CommentOutActivity, DWF.Activities.WorkFlow";



        public ActivityDesignerProxy()
        {
            _workflowDesigner = new WorkflowDesigner();

            var designerConfigurationService = _workflowDesigner.Context.Services.GetService<DesignerConfigurationService>();
            designerConfigurationService.TargetFrameworkName = new System.Runtime.Versioning.FrameworkName(".NETFramework", new Version(4, 6, 2));
            designerConfigurationService.LoadingFromUntrustedSourceEnabled = true;
            designerConfigurationService.AnnotationEnabled = true;
            //designerConfigurationService.BackgroundValidationEnabled = true;
            designerConfigurationService.PanModeEnabled = true;


            new DesignerMetadata().Register();

            var hashTable = new System.Collections.Hashtable();
            hashTable.Add(WorkflowDesignerColors.PropertyInspectorBorderBrushKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#00FFFFFF")));
            hashTable.Add(WorkflowDesignerColors.PropertyInspectorSelectedBackgroundBrushKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#D9DDF9")));
            hashTable.Add(WorkflowDesignerColors.PropertyInspectorSelectedForegroundBrushKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#000000")));

            hashTable.Add(WorkflowDesignerColors.DesignerViewShellBarCaptionActiveColorKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#000000")));
            hashTable.Add(WorkflowDesignerColors.DesignerViewShellBarCaptionColorKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#999999")));
            hashTable.Add(WorkflowDesignerColors.DesignerViewShellBarColorGradientBeginKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#E4E4E4")));
            hashTable.Add(WorkflowDesignerColors.DesignerViewShellBarColorGradientEndKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#E4E4E4")));
            hashTable.Add(WorkflowDesignerColors.DesignerViewShellBarHoverColorGradientBeginKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#E9E9E9")));
            hashTable.Add(WorkflowDesignerColors.DesignerViewShellBarHoverColorGradientEndKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#E9E9E9")));
            hashTable.Add(WorkflowDesignerColors.DesignerViewShellBarSelectedColorGradientBeginKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#FFFFFF")));
            hashTable.Add(WorkflowDesignerColors.DesignerViewShellBarSelectedColorGradientEndKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#FFFFFF")));

            hashTable.Add(WorkflowDesignerColors.DesignerViewExpandAllCollapseAllButtonMouseOverColorKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#333333")));
            hashTable.Add(WorkflowDesignerColors.DesignerViewExpandAllCollapseAllPressedColorKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#999999")));
            hashTable.Add(WorkflowDesignerColors.DesignerViewExpandAllCollapseAllButtonColorKey, new System.Windows.Media.SolidColorBrush((System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#999999")));

            _workflowDesigner.PropertyInspectorFontAndColorData = System.Xaml.XamlServices.Save(hashTable);

            _workflowDesigner.ModelChanged += (sender, e) =>   // andy 20200615 添加 此种方式在修改批注时触发事件  
            {
                DesignModelChanged?.Invoke(EventArgs.Empty);
            };

        }

        public ActivityDesignerProxy(Func<Dictionary<string, string>> projectPropertiesFunc)
            : this()
        {
            var projectProperties = projectPropertiesFunc();

            _projectDirectory = projectProperties["projectDirectory"];
            _workflowDesigner.Context.Services.Publish<IActivityService>(new ActivityService(projectPropertiesFunc, activityNotice));
        }

        /// <summary>
        /// 获取设计器view
        /// </summary>
        /// <returns></returns>
        public INativeHandleContract GetDesignerView()
        {
            return FrameworkElementAdapters.ViewToContractAdapter((FrameworkElement)_workflowDesigner.View);
        }

        /// <summary>
        /// 获取属性栏view
        /// </summary>
        /// <returns></returns>
        public INativeHandleContract GetPropertiesView()
        {
            return FrameworkElementAdapters.ViewToContractAdapter((FrameworkElement)_workflowDesigner.PropertyInspectorView);
        }

        /// <summary>
        /// 获取概要view
        /// </summary>
        /// <returns></returns>
        public INativeHandleContract GetOutlineView()
        {
            return FrameworkElementAdapters.ViewToContractAdapter((FrameworkElement)_workflowDesigner.OutlineView);
        }

        /// <summary>
        /// 刷新
        /// </summary>
        public void Flush()
        {
            this._workflowDesigner.Flush();
        }

        /// <summary>
        /// 是否在错误状态
        /// </summary>
        /// <returns></returns>
        public bool IsInErrorState()
        {
            return this._workflowDesigner.IsInErrorState();
        }

        /// <summary>
        /// 加载
        /// </summary>
        /// <param name="fileName"></param>
        public void Load(string fileName)
        {
            _workflowFilePath = fileName;

            this._workflowDesigner.Load(fileName);//设计器加载
            var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();//获取模型服务

            if (modelService != null)
            {
                //modelService.ModelChanged += (sender, e) =>  // andy 20200615 注销 此种方式在修改批注时 不触发事件  
                //{
                //    DesignModelChanged?.Invoke(EventArgs.Empty);
                //};

                modelService.ModelChanged += (sender, e) =>
                {
                    ModelChanged?.Invoke(_workflowDesigner, e);
                };

                // Oliver 2021-06-15 添加“屏蔽活动”弹出菜单
                MenuItem menuItem = null;
                menuItem = new MenuItem();
                menuItem.Tag = "note";
                menuItem.Header = LocalizationProvider.GetLocalizedString("WinMain_Menu_Edit_CommentOut");  // "屏蔽活动";
                menuItem.InputGestureText = "Ctrl+D";
                menuItem.Click += (sender, e) =>
                {
                    this.Notes();
                };
                this._workflowDesigner.Context.Services.GetService<DesignerView>().ContextMenu.Items.Add(menuItem);

                menuItem = new MenuItem();
                menuItem.Tag = "cancleNote";
                menuItem.Header = LocalizationProvider.GetLocalizedString("WinMain_Menu_Edit_CommentOutUndo");  //"取消屏蔽";
                menuItem.InputGestureText = "Ctrl+P";
                menuItem.Click += (sender, e) =>
                {
                    this.CancelNotes();
                };
                this._workflowDesigner.Context.Services.GetService<DesignerView>().ContextMenu.Items.Add(menuItem);
                this._workflowDesigner.Context.Items.Subscribe<Selection>(OnItemSelected);
            }
        }

        /// <summary>
        /// 选中节点
        /// </summary>
        /// <param name="item"></param>
        private void OnItemSelected(Selection item)
        {
            ModelItem mi = item.PrimarySelection;
            if (mi != null)
            {
                // Oliver 2021-06-15 如果选中 是已经“注释活动”，则开启“取消注释”菜单项可用
                bool isCancelNote = mi.GetCurrentValue().GetType().FullName.Equals(CommentOutActivityTypeName.Split(',')[0]);
                foreach (var itemMenu in this._workflowDesigner.Context.Services.GetService<DesignerView>().ContextMenu.Items)
                {
                    if (itemMenu is MenuItem)
                    {
                        if (((MenuItem)itemMenu).Tag?.ToString() == "note")
                        {
                            //debug状态下，菜单项不可用
                            ((MenuItem)itemMenu).IsEnabled = !_workflowDesigner.Context.Services.GetService<DesignerView>().IsReadOnly;
                        }
                        if (((MenuItem)itemMenu).Tag?.ToString() == "cancleNote")
                        {
                            ((MenuItem)itemMenu).IsEnabled = isCancelNote
                                                                &&
                                                                !_workflowDesigner.Context.Services.GetService<DesignerView>().IsReadOnly;
                        }
                    }
                }
            }
        }

        public void Load(string fileName, List<BreakpointInfo> breakpointInfos)
        {
            this.Load(fileName);
            loadBreakPoint(breakpointInfos);
        }

        private void loadBreakPoint(List<BreakpointInfo> breakpointInfos)
        {
            try
            {
                var debugView = this._workflowDesigner.DebugManagerView;
                var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();

                var locationMapping = refreshSourceLocationMapping(debugView, modelService);//updateSourceLocationMappingInDebuggerService();//不能加载没有动态ID号的activites  2021.1.25 Carl

                var srcLocs = from pair in locationMapping
                              from bp in breakpointInfos
                              where bp.RefId == WorkflowViewState.GetIdRef((Activity)pair.Key) && bp.ActivityType == pair.Key.GetType().FullName
                              select new { SrcLoc = pair.Value, Type = bp.BreakpointType };

                foreach (var srcLoc in srcLocs)
                {
                    if (srcLoc.Type == EBreakpointType.Enabled)
                    {
                        this._workflowDesigner.DebugManagerView.UpdateBreakpoint(srcLoc.SrcLoc, BreakpointTypes.Enabled | BreakpointTypes.Bounded);
                    }
                    else
                    {
                        this._workflowDesigner.DebugManagerView.UpdateBreakpoint(srcLoc.SrcLoc, BreakpointTypes.Bounded);
                    }
                }
            }
            catch { }
        }

        /// <summary>
        /// 加载
        /// </summary>
        public void Load()
        {
            this._workflowDesigner.Load();
        }

        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="fileName"></param>
        public void Save(string fileName)
        {
            this._workflowDesigner.Save(fileName);
            var list = ChangeArgument();
            if (list != null)
            {
                PropertyModelChanged?.Invoke(new ArgumentEventArgs(list));
            }
        }

        public IEnumerable<ValidationInfo> Validate()
        {
            List<ValidationInfo> infos = new List<ValidationInfo>();
            try
            {
                _workflowDesigner.Flush();
                Activity root = ActivityXamlServices.Load(new StringReader(_workflowDesigner.Text));
                ValidationResults results = ActivityValidationServices.Validate(root);

                foreach (var error in results.Errors)
                {
                    infos.Add(new ValidationInfo(error));
                }

                foreach (var warning in results.Warnings)
                {
                    infos.Add(new ValidationInfo(warning));
                }
            }
            catch (Exception ex)
            {
                infos.Add(new ValidationInfo(ex));
            }

            return infos;
        }

        /// <summary>
        /// 获取xaml
        /// </summary>
        /// <returns></returns>
        public string GetXaml()
        {
            this._workflowDesigner.Flush();
            return this._workflowDesigner.Text;
        }

        #region 操作设计器
        public string GetRootActivityTypeName()
        {
            object rootInstance = getRootInstance();
            Activity rootElement = getRootWorkflowElement(rootInstance);

            return rootElement?.GetType().Name;
        }

        public string GetRootActivityCode()
        {
            object rootInstance = getRootInstance();
            Activity rootElement = getRootWorkflowElement(rootInstance);

            return rootElement?.GetHashCode().ToString();
        }

        public void SetActivityByCode(string activityCode, IDictionary<string, object> param)
        {
            var modelService = _workflowDesigner.Context.Services.GetService<System.Activities.Presentation.Services.ModelService>();//获取模型服务
            var models = modelService.Find(modelService.Root, (type) => type.IsSubclassOf(typeof(NativeActivity)) || type.IsSubclassOf(typeof(CodeActivity)));//查找所有活动
            var currentModel = models.FirstOrDefault(item => item.GetCurrentValue()?.GetHashCode().ToString() == activityCode);//找到id相同的
            if (currentModel != null)
            {
                foreach (var pa in param)
                {
                    setActivityValue(currentModel.GetCurrentValue() as Activity, pa.Key, pa.Value); //设置参数
                }
            }
        }

        /// <summary>
        /// 添加活动到指定的Sequence中
        /// </summary>
        /// <param name="parentDisplayName"></param>
        /// <param name="activityTypeName"></param>
        /// <param name="param"></param>
        public string AddActivityByParentCode(string parentCode, string activityTypeName, IDictionary<string, object> param)
        {
            var activityType = Type.GetType(activityTypeName, true);//获取活动类型
            var activity = Activator.CreateInstance(activityType) as Activity;//实例化活

            if (activity != null)
            {
                if (param != null)
                {
                    foreach (var pa in param)
                    {
                        setActivityValue(activity, pa.Key, pa.Value); //设置参数
                    }
                }

                var nativeType = typeof(NativeActivity);
                var codeType = typeof(CodeActivity);

                var modelService = _workflowDesigner.Context.Services.GetService<System.Activities.Presentation.Services.ModelService>();//获取模型服务
                var models = modelService.Find(modelService.Root, (type) => type.IsSubclassOf(nativeType) || type.IsSubclassOf(codeType));//查找所有活动
                var currentModel = models.FirstOrDefault(item => item.GetCurrentValue()?.GetHashCode().ToString() == parentCode);//找到code相同的
                if (currentModel != null)
                {
                    currentModel.Properties["Activities"]?.Collection.Add(activity);//添加活动
                }

                var newmodels = modelService.Find(modelService.Root, (type) => type.IsSubclassOf(nativeType) || type.IsSubclassOf(codeType))
                    .Where(item =>
                {
                    var id = item.Properties["Id"].Value;
                    return id == null || string.IsNullOrEmpty(id.ToString());
                }).
                Select(item => new { TypeName = item.GetCurrentValue()?.GetType().FullName, DisplayName = item.Properties["DisplayName"].Value.ToString(), Code = item.GetCurrentValue()?.GetHashCode() });

                return Share.Serialization.JsonHelper.Serialize(newmodels);
            }

            return String.Empty;
        }

        /// <summary>
        /// 设置活动属性值
        /// </summary>
        /// <param name="activity"></param>
        /// <param name="propertyName"></param>
        /// <param name="value"></param>
        private void setActivityValue(Activity activity, string propertyName, object value)
        {
            Type activityType = activity.GetType();
            var propInfo = activityType.GetProperty(propertyName);
            if (propInfo != null)
            {
                var argValue = Activator.CreateInstance(propInfo.PropertyType, value);
                activityType.GetProperty(propertyName).SetValue(activity, argValue, null);
            }
        }
        #region 参数变更
        public List<ProjectParam> ChangeArgument()
        {
            if (System.IO.Path.GetFileName(_workflowFilePath) == "main.xaml")
            {
                ModelTreeManager mtm = _workflowDesigner.Context.Services.GetService<ModelTreeManager>();
                ModelItem root = mtm.Root;
                ModelItemCollection argsAndProperties = root.Properties["Properties"].Collection;
                var propertyItem = argsAndProperties.Source.ComputedValue;
                var argumentItem = propertyItem as KeyedCollection<string, DynamicActivityProperty>;
                List<ProjectParam> projectParams = new List<ProjectParam>();
                foreach (var items in argumentItem)
                {
                    if (items != null)
                    {
                        var item = items as DynamicActivityProperty;

                        if (item.Value != null)
                        {
                            var typeName = item.Type.FullName;

                            if (typeName.Contains("System.Decimal"))
                            {
                                //item.Value = item.Value.ToString().Replace("[", "").Replace("]", "").Replace("d", "");
                                var argumentValue = item.Value as InArgument<decimal>;
                                if (argumentValue == null)
                                    continue;
                                var expressionText = argumentValue.Expression.GetType().GetProperty("ExpressionText", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);

                                projectParams.Add(new ProjectParam
                                {
                                    Name = item.Name,
                                    InOrOut = "Input",
                                    ParamType = EProjectParamType.Number,
                                    Value = expressionText.GetValue(argumentValue.Expression).ToString().Replace("d", ""),
                                    Description = ""
                                });
                            }
                            else if (typeName.Contains("System.Boolean"))
                            {
                                var argumentValue = item.Value as InArgument<Boolean>;
                                if (argumentValue == null)
                                    continue;
                                projectParams.Add(new ProjectParam
                                {
                                    Name = item.Name,
                                    InOrOut = "Input",
                                    ParamType = EProjectParamType.Boolean,
                                    Value = argumentValue.Expression.ToString(),
                                    Description = ""
                                });
                            }
                            else if (typeName.Contains("System.String"))
                            {
                                var argumentValue = item.Value as InArgument<string>;
                                if (argumentValue == null)
                                    continue;
                                projectParams.Add(new ProjectParam
                                {
                                    Name = item.Name,
                                    InOrOut = "Input",
                                    ParamType = EProjectParamType.String,
                                    Value = argumentValue.Expression.ToString(),
                                    Description = ""
                                });
                            }
                        }
                        else if (item.Type.Name.Contains("OutArgument"))
                        {
                            var typeName = item.Type.FullName;

                            if (typeName.Contains("System.Decimal"))
                            {
                                projectParams.Add(new ProjectParam
                                {
                                    Name = item.Name,
                                    InOrOut = "Output",
                                    ParamType = EProjectParamType.Number,
                                    Value = "",
                                    Description = ""
                                });
                            }
                            else if (typeName.Contains("System.Boolean"))
                            {
                                projectParams.Add(new ProjectParam
                                {
                                    Name = item.Name,
                                    InOrOut = "Output",
                                    ParamType = EProjectParamType.Boolean,
                                    Value = "",
                                    Description = ""
                                });
                            }
                            else if (typeName.Contains("System.String"))
                            {
                                projectParams.Add(new ProjectParam
                                {
                                    Name = item.Name,
                                    InOrOut = "Output",
                                    ParamType = EProjectParamType.String,
                                    Value = "",
                                    Description = ""
                                });
                            }
                        }
                    }
                }
                return projectParams;
            }
            return null;
        }
        public void SetChangeArgument(List<ProjectParam> projectParams)
        {
            foreach (var projectItem in projectParams)
            {
                if (projectItem.InOrOut == "Input")
                {
                    SetInArgument(projectItem);
                }
                else if (projectItem.InOrOut == "Output")
                {
                    SetOutArgument(projectItem);
                }
            }
        }
        public void SetInArgument(ProjectParam projectParam)
        {
            var argument = new object();

            switch (projectParam.ParamType)
            {
                case EProjectParamType.Number: argument = Decimal.Parse(projectParam.Value); break;
                case EProjectParamType.Boolean: argument = projectParam.Value.ToLower() == "true" ? true : false; break;
                case EProjectParamType.String: argument = projectParam.Value; break;
                case EProjectParamType.File: argument = projectParam.Value; break;
            }

            var genericType = argument.GetType();
            Type inArgumentType = typeof(InArgument<>);
            Type constructedType = inArgumentType.MakeGenericType(genericType);

            ModelTreeManager mtm = _workflowDesigner.Context.Services.GetService<ModelTreeManager>();
            ModelItem root = mtm.Root;
            ModelItemCollection argsAndProperties = root.Properties["Properties"].Collection;
            var propertyItem = argsAndProperties.Source.ComputedValue;
            var argumentItem = propertyItem as KeyedCollection<string, DynamicActivityProperty>;
            var existence = false;

            foreach (var items in argumentItem)
            {
                if (items != null)
                {
                    var item = items as DynamicActivityProperty;

                    if (projectParam.Name == item.Name) //workflow里是否存在
                    {
                        var ox = argsAndProperties.Remove(item);
                        argsAndProperties.Add(new DynamicActivityProperty
                        {
                            Name = projectParam.Name,
                            Type = constructedType,
                            Value = projectParam.ParamType == EProjectParamType.Number ? "[" + projectParam.Value + "d]" : projectParam.Value
                        });
                        existence = true;
                        break;
                    }
                }
            }
            if (!existence)//向workflow新添加参数
            {
                argsAndProperties.Add(new DynamicActivityProperty
                {
                    Name = projectParam.Name,
                    Type = constructedType,
                    Value = projectParam.ParamType == EProjectParamType.Number ? "[" + projectParam.Value + "d]" : projectParam.Value,
                    Attributes = { new RequiredArgumentAttribute() {

                    }},
                });
            }

        }
        public void SetOutArgument(ProjectParam projectParam)
        {
            var argument = new object();
            switch (projectParam.ParamType)
            {
                case EProjectParamType.Number: argument = decimal.Parse(projectParam.Value); break;
                case EProjectParamType.Boolean: argument = projectParam.Value.ToLower() == "true" ? true : false; break;
                case EProjectParamType.String: argument = projectParam.Value; break;
                case EProjectParamType.File: argument = projectParam.Value; break;
            }

            var genericType = argument.GetType();
            Type outArgumentType = typeof(OutArgument<>);
            Type constructedType = outArgumentType.MakeGenericType(genericType);

            ModelTreeManager mtm = _workflowDesigner.Context.Services.GetService<ModelTreeManager>();
            ModelItem root = mtm.Root;
            ModelItemCollection argsAndProperties = root.Properties["Properties"].Collection;
            var propertyItem = argsAndProperties.Source.ComputedValue;
            var argumentItem = propertyItem as KeyedCollection<string, DynamicActivityProperty>;
            var existence = false;
            foreach (var items in argumentItem)
            {
                if (items != null)
                {
                    var item = items as DynamicActivityProperty;

                    if (projectParam.Name == item.Name) //workflow里是否存在
                    {
                        var ox = argsAndProperties.Remove(item);
                        argsAndProperties.Add(new DynamicActivityProperty
                        {
                            Name = projectParam.Name,
                            Type = constructedType
                        });
                        existence = true;
                        break;
                    }
                }
            }
            if (!existence)//向workflow新添加参数
            {
                argsAndProperties.Add(new DynamicActivityProperty
                {
                    Name = projectParam.Name,
                    Type = constructedType
                });
            }
        }
        #endregion

        #endregion

        /// <summary>
        /// 模型改变
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void modelChanged(object sender, ModelChangedEventArgs e)
        {
            if (e.ModelChangeInfo.ModelChangeType == ModelChangeType.CollectionItemAdded || e.ModelChangeInfo.ModelChangeType == ModelChangeType.PropertyChanged || e.ModelChangeInfo.ModelChangeType == ModelChangeType.DictionaryKeyValueAdded)
            {
                var modelItem = e.ModelChangeInfo.Value;
                if (modelItem != null)
                {
                    var activity = modelItem.GetCurrentValue();

                    if (activity is System.Activities.Statements.FlowStep)//处理flowchar 文件类型
                    {
                        var flowStep = activity as System.Activities.Statements.FlowStep;
                        if (flowStep != null)
                        {
                            setActivityProperties(flowStep.Action);
                        }
                    }
                    else if (activity is Activity)
                    {
                        setActivityProperties(activity as Activity);
                    }
                }
            }
        }

        /// <summary>
        /// 设置活动属性
        /// </summary>
        /// <param name="activity"></param>
        private void setActivityProperties(Activity activity)
        {
            if (activity != null)
            {
                var activityType = activity.GetType();

                var piDirectory = activityType.GetProperty("ProjectDirectory");//工程目录
                if (piDirectory != null)
                {
                    piDirectory.SetValue(activity, _projectDirectory);
                }

                var piNotice = activityType.GetProperty("Notice");//活动通知
                if (piNotice != null)
                {
                    piNotice.SetValue(activity, ActivityNotice);
                }
            }
        }

        private void activityNotice(string msg, string data)
        {
            if (ActivityNotice != null)
            {
                ActivityNotice(msg, data);
            }
        }

        #region 操作命令
        public void CutCommand()
        {
            var designerView = _workflowDesigner.Context.Services.GetService<DesignerView>();
            ((RoutedCommand)DesignerView.CutCommand).Execute(null, designerView);
        }

        public void CopyCommand()
        {
            var designerView = _workflowDesigner.Context.Services.GetService<DesignerView>();
            ((RoutedCommand)DesignerView.CopyCommand).Execute(null, designerView);
        }

        public void PasteCommand()
        {
            var designerView = _workflowDesigner.Context.Services.GetService<DesignerView>();
            ((RoutedCommand)DesignerView.PasteCommand).Execute(null, designerView);
        }

        public void UndoCommand()
        {
            var designerView = _workflowDesigner.Context.Services.GetService<DesignerView>();
            ((RoutedCommand)DesignerView.UndoCommand).Execute(null, designerView);
        }

        public void RedoCommand()
        {
            var designerView = _workflowDesigner.Context.Services.GetService<DesignerView>();
            ((RoutedCommand)DesignerView.RedoCommand).Execute(null, designerView);
        }
        /// <summary>
        /// 注释
        /// </summary>
        public void Notes()
        {
            ModelItem modelItem_Selected = this._workflowDesigner.Context.Items.GetValue<Selection>().PrimarySelection;
            if (modelItem_Selected != null)
            {
                Activity activity_Selected = modelItem_Selected.GetCurrentValue() as Activity;
                if (activity_Selected != null)
                {
                    var typeofCommentOutActivity = Type.GetType(CommentOutActivityTypeName, false);
                    if (typeofCommentOutActivity != null)  //是否有对应的活动包
                    {
                        var isFlowChat = modelItem_Selected.Parent?.GetCurrentValue() is System.Activities.Statements.FlowStep;  // FlowChat|Sequence
                        if (isFlowChat)
                        {
                            //is FlowCha 是流程图
                            //注释选中活动
                            var Activity_Selected_New = Activator.CreateInstance(typeofCommentOutActivity) as Activity;  //创建活动实例
                            var sequence = new Sequence()
                            {
                                Activities = { activity_Selected }
                            };
                            Activity_Selected_New.GetType().GetProperty("Body").SetValue(Activity_Selected_New, sequence);  //硬编码：禁用活动的"Body"属性

                            //查找位置，并将注册的活动添加到选中活动的位置
                            var nativeType = typeof(NativeActivity);
                            var codeType = typeof(CodeActivity);
                            var modelService = _workflowDesigner.Context.Services.GetService<System.Activities.Presentation.Services.ModelService>();//获取模型服务
                            var models = modelService.Find(modelService.Root, (type) => type.IsSubclassOf(typeof(Activity))).ToList();//查找所有活动

                            //取得父容器控件
                            var currentModel_Parent = modelItem_Selected.Parent?.Parent?.Parent;  //找到父控件

                            if (currentModel_Parent != null)  //父活动不为空
                            {
                                var flowchart = modelItem_Selected.Parent.Parent.Parent.GetCurrentValue() as Flowchart;

                                //设置 屏蔽活动
                                int modelItemIndex = 0;

                                for (int i = 0; i < flowchart.Nodes.Count; i++)
                                {
                                    var itemStep = flowchart.Nodes[i] as FlowStep;
                                    if (itemStep.Action.Equals(activity_Selected))
                                    {
                                        modelItemIndex = i;
                                        break;
                                    }
                                }

                                //反射方式添加新元素
                                using (var scope = currentModel_Parent.BeginEdit())
                                {
                                    //删除断点（注：一定要在屏蔽前删除断点！！）
                                    this.DeleteBreakPointByHashCode(activity_Selected.GetHashCode());

                                    //设置屏蔽


                                    ModelItem resultModel = null;
                                    foreach (var item in currentModel_Parent.Properties["Nodes"].Collection[modelItemIndex].Properties)
                                    {
                                        if (item.PropertyType == typeof(System.Activities.Activity))
                                        {
                                            //设置屏蔽
                                            resultModel = item.SetValue(Activity_Selected_New);
                                            break;
                                        }
                                    }

                                    //todo:设置焦点
                                    var modelItem_NewHashCode = resultModel.GetCurrentValue().GetHashCode();
                                    if (modelItem_NewHashCode > 0)
                                    {
                                        this.ActivitySelectionByHashCode(modelItem_NewHashCode);
                                    }

                                    scope.Complete();
                                }

                            }//endif 父活动不为空
                        }//endif is FlowCha 是流程图
                        else
                        {
                            //is Sequence 是序列图
                            if (modelItem_Selected.Parent != null && modelItem_Selected.Parent.Parent != null)  //避免选中最外层活动
                            {
                                //注释选中活动
                                var Activity_Selected_New = Activator.CreateInstance(typeofCommentOutActivity) as Activity;  //创建活动实例
                                var sequence = new Sequence()
                                {
                                    Activities = { activity_Selected }
                                };
                                Activity_Selected_New.GetType().GetProperty("Body").SetValue(Activity_Selected_New, sequence);  //硬编码：禁用活动的"Body"属性

                                //查找位置，并将注册的活动添加到选中活动的位置
                                var nativeType = typeof(NativeActivity);
                                var codeType = typeof(CodeActivity);
                                var modelService = _workflowDesigner.Context.Services.GetService<System.Activities.Presentation.Services.ModelService>();//获取模型服务
                                var models = modelService.Find(modelService.Root, (type) => type.IsSubclassOf(typeof(Activity))).ToList();//查找所有活动

                                //取得父容器控件
                                var parentCode = modelItem_Selected.Parent?.Parent?.GetCurrentValue()?.GetHashCode().ToString();
                                if (modelItem_Selected.Parent?.GetCurrentValue() is System.Activities.Activity)  //特殊情况选择的活动
                                {
                                    parentCode = modelItem_Selected.Parent?.GetCurrentValue()?.GetHashCode().ToString();
                                }
                                var currentModel_Parent = models.FirstOrDefault(item => item.GetCurrentValue()?.GetHashCode().ToString() == parentCode);//找到父活动

                                if (currentModel_Parent != null)  //父活动不为空
                                {
                                    //判断上层是否是Sequence
                                    var parentIsSequence = (Activity)currentModel_Parent.GetCurrentValue() is System.Activities.Statements.Sequence;
                                    if (!parentIsSequence)
                                    {
                                        //上层不是Sequence，寻找上层的"Body"
                                        foreach (var property in currentModel_Parent.Properties)
                                        {
                                            if (property.Value?.GetCurrentValue().GetHashCode() == activity_Selected.GetHashCode())
                                            {
                                                //原始的有效方法
                                                using (var scope = currentModel_Parent.BeginEdit())
                                                {
                                                    //删除断点（注：一定要在屏蔽前删除断点！！）
                                                    this.DeleteBreakPointByHashCode(activity_Selected.GetHashCode());

                                                    //设置屏蔽
                                                    var resultModel = property.SetValue(Activity_Selected_New);

                                                    //设置焦点
                                                    var modelItem_NewHashCode = resultModel.GetCurrentValue().GetHashCode();
                                                    if (modelItem_NewHashCode > 0)
                                                    {
                                                        this.ActivitySelectionByHashCode(modelItem_NewHashCode);
                                                    }

                                                    scope.Complete();
                                                }
                                                break;
                                            }
                                        }
                                    }//endif 上层是Sequence
                                    else
                                    {
                                        //设置屏蔽
                                        //查找选中元素的位置
                                        int modelItemIndex = 0;
                                        foreach (var item in currentModel_Parent.Properties["Activities"]?.Collection)
                                        {
                                            if (item.Equals(modelItem_Selected))
                                            {
                                                break;
                                            }
                                            modelItemIndex++;
                                        }

                                        //直接操作数组法，有效，//但undo体验不良好，加入事务嵌套之后，效果非常好
                                        using (var scope = currentModel_Parent.BeginEdit())
                                        {
                                            //删除断点（注：一定要在屏蔽前删除断点！！）
                                            this.DeleteBreakPointByHashCode(activity_Selected.GetHashCode());

                                            currentModel_Parent.Properties["Activities"]?.Collection.Remove(activity_Selected); //移除选中的活动
                                            var resultModel = currentModel_Parent.Properties["Activities"]?.Collection.Insert(modelItemIndex, Activity_Selected_New); //插入屏蔽活动

                                            //设置焦点
                                            var modelItem_NewHashCode = resultModel.GetCurrentValue().GetHashCode();
                                            if (modelItem_NewHashCode > 0)
                                            {
                                                this.ActivitySelectionByHashCode(modelItem_NewHashCode);
                                            }

                                            scope.Complete();  //标记事务结束
                                        }

                                    }//endelse 上层不是是Sequence
                                }//endif 父活动不为空
                            }//endif currentModel_Parent != null 所选活动的Parent不为空
                        }//endelse is Sequence 是序列图
                    }//endif 是否有对应的活动包
                    else
                    {
                        //对应的活动包 DWF.Activities.WorkFlow

                    }//endelse 是否有对应的活动包
                }
            }
        }
        /// <summary>
        /// 取消注释
        /// </summary>
        public void CancelNotes()
        {
            ModelItem modelItem_Selected = this._workflowDesigner.Context.Items.GetValue<Selection>().PrimarySelection;
            if (modelItem_Selected != null)
            {
                Activity activity_Selected = modelItem_Selected.GetCurrentValue() as Activity;
                //如果选中不是“注释掉”最外层的活动，则退出
                if (!modelItem_Selected.GetCurrentValue().GetType().FullName.Equals(CommentOutActivityTypeName.Split(',')[0]))
                {
                    return;
                }
                //判断选中的注释活动下级是否为Sequence Oliver add 2021-06-29
                bool isCompleteCommentOutActivity = activity_Selected.GetType().GetProperty("Body").GetValue(activity_Selected) is Sequence;
                if (!isCompleteCommentOutActivity)
                {
                    if (!(activity_Selected.GetType().GetProperty("Body").GetValue(activity_Selected) is Activity))
                    {
                        return;  //如果选中项的下级既不是完整的注释活动，也不是注释活动的外层，直接退出  p.s.目前看这种情况相当诡异，还无法预料如何产生
                    }
                }
                var sequence_Decide = activity_Selected.GetType().GetProperty("Body").GetValue(activity_Selected) as Sequence;  //硬编码：禁用活动的"Body"属性
                if (sequence_Decide?.Activities?.Count <= 0)
                {
                    //空的“注释掉”活动，直接退出
                    return;
                }
                if (activity_Selected != null)
                {
                    var typeofCommentOutActivity = Type.GetType(CommentOutActivityTypeName, false);
                    if (typeofCommentOutActivity != null)  //是否有对应的活动包
                    {
                        var isFlowChat = modelItem_Selected.Parent?.GetCurrentValue() is System.Activities.Statements.FlowStep;  // FlowChat|Sequence
                        if (isFlowChat)
                        {
                            //is FlowCha 是流程图
                            //释放已注释的活动
                            var normalItem = sequence_Decide?.Activities[0];
                            //判断选中的注释活动下级是否为Sequence Oliver add 2021-06-29
                            if (!isCompleteCommentOutActivity)
                            {
                                normalItem = activity_Selected.GetType().GetProperty("Body").GetValue(activity_Selected) as Activity;
                            }

                            //查找位置，并将注册的活动添加到选中活动的位置
                            var nativeType = typeof(NativeActivity);
                            var codeType = typeof(CodeActivity);
                            var modelService = _workflowDesigner.Context.Services.GetService<System.Activities.Presentation.Services.ModelService>();//获取模型服务
                            var models = modelService.Find(modelService.Root, (type) => type.IsSubclassOf(typeof(FlowStep))).ToList();//查找所有活动

                            //取得父容器控件
                            var currentModel_Parent = modelItem_Selected.Parent?.Parent?.Parent;  //找到父控件

                            if (currentModel_Parent != null)  //父活动不为空
                            {
                                var flowchart = modelItem_Selected.Parent.Parent.Parent.GetCurrentValue() as Flowchart;

                                using (var scope = currentModel_Parent.BeginEdit())
                                {
                                    ModelItem resultModel = null;

                                    for (int i = 0; i < currentModel_Parent.Properties["Nodes"]?.Collection?.Count; i++)
                                    {
                                        if (
                                            ((FlowStep)currentModel_Parent.Properties["Nodes"].Collection[i].GetCurrentValue()).Action.GetHashCode() == activity_Selected.GetHashCode()
                                            )  //选中状态下，动态Id相同
                                        {
                                            var pros = currentModel_Parent.Properties["Nodes"].Collection[i].Properties;
                                            foreach (var property in pros)
                                            {
                                                if (property.PropertyType == typeof(System.Activities.Activity))
                                                {
                                                    resultModel = property.SetValue(normalItem);
                                                    break;
                                                }
                                            }
                                            break;
                                        }
                                    }
                                    //todo:设置焦点
                                    var modelItem_NewHashCode = resultModel.GetCurrentValue().GetHashCode();
                                    if (modelItem_NewHashCode > 0)
                                    {
                                        this.ActivitySelectionByHashCode(modelItem_NewHashCode);
                                    }

                                    scope.Complete();
                                }
                            }//endif 父活动不为空
                        }//endif is FlowCha 是流程图
                        else
                        {
                            //is Sequence 是序列图
                            if (modelItem_Selected.Parent != null && modelItem_Selected.Parent.Parent != null)  //避免选中最外层
                            {
                                //释放已注释的活动
                                var normalItem = sequence_Decide?.Activities[0];
                                //判断选中的注释活动下级是否为Sequence Oliver add 2021-06-29
                                if (!isCompleteCommentOutActivity)
                                {
                                    normalItem = activity_Selected.GetType().GetProperty("Body").GetValue(activity_Selected) as Activity;
                                }

                                //查找位置，并将注册的活动添加到选中活动的位置
                                var nativeType = typeof(NativeActivity);
                                var codeType = typeof(CodeActivity);
                                var modelService = _workflowDesigner.Context.Services.GetService<System.Activities.Presentation.Services.ModelService>();//获取模型服务
                                var models = modelService.Find(modelService.Root, (type) => type.IsSubclassOf(typeof(Activity))).ToList();//查找所有活动

                                //取得父容器控件
                                var parentCode = modelItem_Selected.Parent?.Parent?.GetCurrentValue()?.GetHashCode().ToString();
                                if (modelItem_Selected.Parent?.GetCurrentValue() is System.Activities.Activity)  //特殊情况选择的活动
                                {
                                    parentCode = modelItem_Selected.Parent?.GetCurrentValue()?.GetHashCode().ToString();
                                }
                                var currentModel_Parent = models.FirstOrDefault(item => item.GetCurrentValue()?.GetHashCode().ToString() == parentCode);//找到父活动

                                if (currentModel_Parent != null)  //父活动不为空
                                {
                                    var modelItem_NewHashCode = -1;

                                    //判断上层是否是Sequence
                                    var parentIsSequence = (Activity)currentModel_Parent.GetCurrentValue() is System.Activities.Statements.Sequence;
                                    if (!parentIsSequence)
                                    {
                                        using (var scope = currentModel_Parent.BeginEdit())
                                        {
                                            //上层不是Sequence，寻找上层的"Body"
                                            foreach (var property in currentModel_Parent.Properties)
                                            {
                                                if (property.Value?.GetCurrentValue().GetHashCode() == activity_Selected.GetHashCode())
                                                {
                                                    modelItem_NewHashCode = property.SetValue(normalItem)
                                                                                .GetCurrentValue().GetHashCode();
                                                    break;
                                                }
                                            }

                                            //设置焦点
                                            if (modelItem_NewHashCode > 0)
                                            {
                                                this.ActivitySelectionByHashCode(modelItem_NewHashCode);
                                            }

                                            scope.Complete();
                                        }
                                    }//endif 上层是Sequence
                                    else
                                    {
                                        int modelItemIndex = 0;
                                        foreach (var item in currentModel_Parent.Properties["Activities"]?.Collection)
                                        {
                                            if (item.Equals(modelItem_Selected))
                                            {
                                                break;
                                            }
                                            modelItemIndex++;
                                        }

                                        using (var scope = currentModel_Parent.BeginEdit())
                                        {
                                            currentModel_Parent.Properties["Activities"]?.Collection.Remove(activity_Selected); //移除选中的活动
                                            var resultModel = currentModel_Parent.Properties["Activities"]?.Collection.Insert(modelItemIndex, normalItem); //插入屏蔽活动                                
                                            modelItem_NewHashCode = resultModel.GetCurrentValue().GetHashCode();

                                            //设置焦点
                                            if (modelItem_NewHashCode > 0)
                                            {
                                                this.ActivitySelectionByHashCode(modelItem_NewHashCode);
                                            }

                                            scope.Complete();
                                        }
                                    }//endelse 上层不是是Sequence
                                }//endif 父活动不为空
                            }//endif currentModel_Parent != null 所选活动的Parent不为空
                        }//endelse is Sequence 是序列图
                    }//endif 是否有对应的活动包
                    else
                    {
                        //对应的活动包 DWF.Activities.WorkFlow

                    }//endelse 是否有对应的活动包
                }
            }
        }
        /// <summary>
        /// 焦点到选择 目标活动上 ByHashCode   Oliver 2021-06-10
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="activityDisplayName"></param>
        public void ActivitySelectionByHashCode(int HashCode)
        {
            var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();
            var activities = modelService.Find(modelService.Root, typeof(Activity));
            ModelItem modelItem = activities.FirstOrDefault((model) =>
            {
                Activity activity = model.GetCurrentValue() as Activity;
                return activity != null && activity.GetHashCode() == HashCode;
            });

            modelItem?.Focus();
        }
        /// <summary>
        /// 删除断点 ByHashCode   Oliver 2021-06-10
        /// </summary>
        /// <param name="HashCode"></param>
        public void DeleteBreakPointByHashCode(int HashCode)
        {
            var debugView = this._workflowDesigner.DebugManagerView;
            var modelService = this._workflowDesigner.Context.Services.GetService<ModelService>();
            var locationMapping = refreshSourceLocationMapping(debugView, modelService);
            var idlocpairs = from pair in locationMapping
                             let activity = pair.Key as Activity
                             where activity != null
                             select new { Activity = activity, Location = pair.Value };
            var bpLocations = debugView.GetBreakpointLocations();

            BreakpointInfo breakpoint = null;
            SourceLocation sourceLocation = null;
            foreach (var idlocpair in idlocpairs)
            {
                var isExisting = bpLocations.ContainsKey(idlocpair.Location);
                if (isExisting)
                {
                    if (idlocpair.Activity.GetHashCode().Equals(HashCode))
                    {
                        var bptype = bpLocations[idlocpair.Location];
                        var id = idlocpair.Activity.Id;
                        var name = idlocpair.Activity.DisplayName;
                        var type = idlocpair.Activity.GetType().FullName;
                        var refId = WorkflowViewState.GetIdRef(idlocpair.Activity);
                        switch (bptype)
                        {
                            case BreakpointTypes.Enabled: breakpoint = new BreakpointInfo(id, name, type, EBreakpointType.Enabled, refId); break;
                            case BreakpointTypes.Bounded: breakpoint = new BreakpointInfo(id, name, type, EBreakpointType.Bounded, refId); break;
                            case BreakpointTypes.Enabled | BreakpointTypes.Bounded: breakpoint = new BreakpointInfo(id, name, type, EBreakpointType.Enabled, refId); break;
                        }

                        sourceLocation = idlocpair.Location;

                        break;
                    }
                }
            }
            if (breakpoint != null)
            {
                debugView.DeleteBreakpoint(sourceLocation);
                DeleteBreakPoint(breakpoint);
            }
        }
        #endregion

        #region 调试
        public void SetReadOnly(bool isReadOnly)
        {
            _workflowDesigner.Context.Items.GetValue<ReadOnlyState>().IsReadOnly = isReadOnly;
            var designerView = _workflowDesigner.Context.Services.GetService<DesignerView>();
            designerView.IsReadOnly = isReadOnly;
        }

        public void DebugStart()
        {
            //_designerSourceLocationMapping = updateSourceLocationMappingInDebuggerService();
        }

        public void DebugEnd()
        {
            this._workflowDesigner.DebugManagerView.CurrentLocation = null;
            //_designerSourceLocationMapping = null;
        }

        public void ClearCurrentLocation()
        {
            this._workflowDesigner.DebugManagerView.CurrentLocation = null;
        }

        public IEnumerable<BreakpointInfo> GetBreakpoints()
        {
            var debugView = this._workflowDesigner.DebugManagerView;
            var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();
            var locationMapping = refreshSourceLocationMapping(debugView, modelService);

            var idlocpairs = from pair in locationMapping
                             let activity = pair.Key as Activity
                             where activity != null
                             select new { Activity = activity, Location = pair.Value };
            var bpLocations = debugView.GetBreakpointLocations();

            List<BreakpointInfo> breakpointInfos = new List<BreakpointInfo>();
            foreach (var idlocpair in idlocpairs)
            {
                var isExisting = bpLocations.ContainsKey(idlocpair.Location);
                if (isExisting)
                {
                    var bptype = bpLocations[idlocpair.Location];
                    var id = idlocpair.Activity.Id;
                    var name = idlocpair.Activity.DisplayName;
                    var type = idlocpair.Activity.GetType().FullName;
                    var refId = WorkflowViewState.GetIdRef(idlocpair.Activity);
                    BreakpointInfo breakpoint = null;
                    switch (bptype)
                    {
                        case BreakpointTypes.Enabled: breakpoint = new BreakpointInfo(id, name, type, EBreakpointType.Enabled, refId); break;
                        case BreakpointTypes.Bounded: breakpoint = new BreakpointInfo(id, name, type, EBreakpointType.Bounded, refId); break;
                        case BreakpointTypes.Enabled | BreakpointTypes.Bounded: breakpoint = new BreakpointInfo(id, name, type, EBreakpointType.Enabled, refId); break;
                    }

                    if (breakpoint != null)
                    {
                        breakpointInfos.Add(breakpoint);
                    }
                }
            }

            return breakpointInfos;
        }

        public bool Debug(string activityId)
        {
            var isHitBreakpoint = false;
            this._workflowDesigner.DebugManagerView.CurrentLocation = null;

            var debugView = this._workflowDesigner.DebugManagerView;
            var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();
            var locationMapping = refreshSourceLocationMapping(debugView, modelService);

            var idlocpairs = from pair in locationMapping
                             let activity = pair.Key as Activity
                             where activity != null
                             select new { activity.Id, pair.Value };

            var srcLoc = idlocpairs.Where(item => item.Id == activityId).Select(item => item.Value).FirstOrDefault();
            if (srcLoc != null)
            {
                var breakpoints = debugView.GetBreakpointLocations();
                var isExisting = breakpoints.ContainsKey(srcLoc);
                if (isExisting)
                {
                    var breakpointtype = breakpoints[srcLoc];

                    if (breakpointtype == (BreakpointTypes.Enabled | BreakpointTypes.Bounded))
                    {
                        this._workflowDesigner.DebugManagerView.CurrentLocation = srcLoc;
                        isHitBreakpoint = true;
                        setActivitySelection(modelService, activityId);
                    }
                }
            }

            return isHitBreakpoint;
        }

        public bool DebugByStep(string activityId)
        {
            var isHitActivity = false;
            this._workflowDesigner.DebugManagerView.CurrentLocation = null;

            var debugView = this._workflowDesigner.DebugManagerView;
            var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();
            var locationMapping = refreshSourceLocationMapping(debugView, modelService);

            var idlocpairs = from pair in locationMapping
                             let activity = pair.Key as Activity
                             where activity != null
                             select new { activity.Id, pair.Value };

            var srcLoc = idlocpairs.Where(item => item.Id == activityId).Select(item => item.Value).FirstOrDefault();
            if (srcLoc != null)
            {
                this._workflowDesigner.DebugManagerView.CurrentLocation = srcLoc;
                isHitActivity = true;
                setActivitySelection(modelService, activityId);
            }

            return isHitActivity;
        }
        #region 断点操作

        public void ToggleBreakPoint()
        {
            ModelItem modelItem = this._workflowDesigner.Context.Items.GetValue<Selection>().PrimarySelection;
            if (modelItem != null)
            {
                Activity activity = modelItem.GetCurrentValue() as Activity;
                if (activity != null)
                {
                    var debugView = this._workflowDesigner.DebugManagerView;
                    var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();

                    var locationMapping = refreshSourceLocationMapping(debugView, modelService);
                    if (locationMapping.ContainsKey(activity))
                    {
                        var id = activity.Id;
                        var name = activity.DisplayName;
                        var type = activity.GetType().FullName;
                        var refId = WorkflowViewState.GetIdRef(activity);
                        SourceLocation srcLoc = locationMapping[activity];

                        var breakpoints = debugView.GetBreakpointLocations();
                        if (breakpoints.ContainsKey(srcLoc))
                        {
                            var breakpointtype = breakpoints[srcLoc];

                            if (breakpointtype == (BreakpointTypes.Enabled | BreakpointTypes.Bounded))
                            {
                                debugView.UpdateBreakpoint(srcLoc, BreakpointTypes.Bounded);
                                if (BreakpointChanged != null)
                                {
                                    BreakpointChanged(new BreakpointEventArgs() { Path = System.IO.Path.GetFileName(_workflowFilePath), Operation = EOperation.Update, Breakpoint = new BreakpointInfo(id, name, type, EBreakpointType.Bounded, refId) });
                                }
                            }
                            else if (breakpointtype == BreakpointTypes.Bounded)
                            {
                                debugView.UpdateBreakpoint(srcLoc, BreakpointTypes.None);
                                if (BreakpointChanged != null)
                                {
                                    BreakpointChanged(new BreakpointEventArgs() { Path = System.IO.Path.GetFileName(_workflowFilePath), Operation = EOperation.Delete, Breakpoint = new BreakpointInfo(id, name, type, EBreakpointType.Bounded, refId) });
                                }
                            }
                        }
                        else
                        {
                            debugView.UpdateBreakpoint(srcLoc, BreakpointTypes.Enabled | BreakpointTypes.Bounded);

                            if (BreakpointChanged != null)
                            {
                                BreakpointChanged(new BreakpointEventArgs() { Path = System.IO.Path.GetFileName(_workflowFilePath), Operation = EOperation.Add, Breakpoint = new BreakpointInfo(id, name, type, EBreakpointType.Enabled, refId) });
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 启用所有断点
        /// </summary>
        public void EnableBreakPoint(IEnumerable<BreakpointInfo> breakpointInfos)
        {
            var debugView = this._workflowDesigner.DebugManagerView;
            var breakpoints = debugView.GetBreakpointLocations();
            foreach (var item in breakpoints)
            {
                debugView.UpdateBreakpoint(item.Key, BreakpointTypes.Enabled | BreakpointTypes.Bounded);
            }
            foreach (BreakpointInfo breakpointInfo in breakpointInfos.ToList())
            {
                if (this._workflowFilePath == breakpointInfo.FullName)
                {
                    BreakpointChanged(new BreakpointEventArgs() { Path = System.IO.Path.GetFileName(_workflowFilePath), Operation = EOperation.Update, Breakpoint = breakpointInfo });
                }
            }
        }
        /// <summary>
        /// 禁用所有断点
        /// </summary>
        public void BoundedBreakPoint(IEnumerable<BreakpointInfo> breakpointInfos)
        {
            var debugView = this._workflowDesigner.DebugManagerView;
            var breakpoints = debugView.GetBreakpointLocations();
            foreach (var item in breakpoints)
            {
                debugView.UpdateBreakpoint(item.Key, BreakpointTypes.Bounded);
            }
            foreach (BreakpointInfo breakpointInfo in breakpointInfos.ToList())
            {
                if (this._workflowFilePath == breakpointInfo.FullName)
                {
                    BreakpointChanged(new BreakpointEventArgs() { Path = System.IO.Path.GetFileName(_workflowFilePath), Operation = EOperation.Update, Breakpoint = breakpointInfo });
                }
            }
        }
        /// <summary>
        /// 删除断点
        /// </summary>
        public void DeleteBreakPoint(BreakpointInfo breakpointInfo)
        {
            var debugView = this._workflowDesigner.DebugManagerView;
            var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();
            var locationMapping = refreshSourceLocationMapping(debugView, modelService);

            var idlocpairs = from pair in locationMapping
                             let activity = pair.Key as Activity
                             where activity != null
                             select new { activity.Id, pair.Value, activity.DisplayName, refid = WorkflowViewState.GetIdRef(activity) };

            var srcLoc = idlocpairs.Where(item => item.Id == breakpointInfo.ActivityId).Select(item => item.Value).ToList();

            if (srcLoc.Count == 1)
            {
                var breakpoints = debugView.GetBreakpointLocations();
                var isExisting = breakpoints.ContainsKey(srcLoc[0]);

                debugView.UpdateBreakpoint(srcLoc[0], BreakpointTypes.None);
            }
            else
            {
                srcLoc = idlocpairs.Where(item => item.Id == breakpointInfo.ActivityId && item.DisplayName == breakpointInfo.ActivityName).Select(item => item.Value).ToList();
                if (srcLoc.Count == 1)
                {
                    var breakpoints = debugView.GetBreakpointLocations();
                    var isExisting = breakpoints.ContainsKey(srcLoc[0]);

                    debugView.UpdateBreakpoint(srcLoc[0], BreakpointTypes.None);
                }
                else
                {
                    srcLoc = idlocpairs.Where(item => item.refid == breakpointInfo.RefId).Select(item => item.Value).ToList();
                    if (srcLoc.Count >= 0)
                    {
                        var breakpoints = debugView.GetBreakpointLocations();
                        var isExisting = breakpoints.ContainsKey(srcLoc[0]);

                        debugView.UpdateBreakpoint(srcLoc[0], BreakpointTypes.None);
                    }
                }
            }
            if (this._workflowFilePath == breakpointInfo.FullName)
            {
                BreakpointChanged(new BreakpointEventArgs() { Path = System.IO.Path.GetFileName(_workflowFilePath), Operation = EOperation.Delete, Breakpoint = breakpointInfo });
            }
        }
        /// <summary>
        /// 删除所有断点
        /// </summary>
        public void DeleteAllBreakPoints()
        {
            var debugView = this._workflowDesigner.DebugManagerView;
            debugView.ResetBreakpoints();
        }
        #endregion

        public void LocateActivityById(string activityId)
        {
            var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();
            setActivitySelection(modelService, activityId);
        }

        private void setActivitySelection(ModelService modelService, string activityId)
        {
            IEnumerable<ModelItem> models = modelService.Find(modelService.Root, typeof(Activity));

            var currentModel = models.FirstOrDefault((modelItem) =>
            {
                Activity activity = modelItem.GetCurrentValue() as Activity;
                return activity != null && activity.Id == activityId;
            });

            currentModel?.Focus();
        }
        /// <summary>
        /// 焦点到选择 目标活动上(未使用)
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="activityDisplayName"></param>
        public void ActivitySelectionById(string id)
        {
            var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();
            var activities = modelService.Find(modelService.Root, typeof(Activity));
            ModelItem modelItem = activities.FirstOrDefault((modelItems) =>
            {
                Activity activity = modelItems.GetCurrentValue() as Activity;
                return activity != null && activity.Id == id;
            });

            modelItem?.Focus();
        }
        /// <summary>
        /// 焦点到选择 目标活动上
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="activityDisplayName"></param>
        public void SetActivitySelectioniByIdRef(string idRef)
        {
            var modelService = _workflowDesigner.Context.Services.GetService<ModelService>();
            var activities = modelService.Find(modelService.Root, typeof(Activity));
            ModelItem modelItem = activities.FirstOrDefault((ModelItem a) => WorkflowViewState.GetIdRef(a.GetCurrentValue()) == idRef);

            modelItem?.Focus();
        }
        private Dictionary<object, SourceLocation> updateSourceLocationMappingInDebuggerService()
        {
            object rootInstance = getRootInstance();
            Dictionary<object, SourceLocation> sourceLocationMapping = new Dictionary<object, SourceLocation>();
            Dictionary<object, SourceLocation> designerSourceLocationMapping = new Dictionary<object, SourceLocation>();

            if (rootInstance != null)
            {
                Activity documentRootElement = getRootWorkflowElement(rootInstance);

                var rootRuntimeWorkflowElement = getRootRuntimeWorkflowElement();

                SourceLocationProvider.CollectMapping(rootRuntimeWorkflowElement, documentRootElement, sourceLocationMapping, this._workflowDesigner.Context.Items.GetValue<WorkflowFileItem>().LoadedFile);

                SourceLocationProvider.CollectMapping(documentRootElement, documentRootElement, designerSourceLocationMapping, this._workflowDesigner.Context.Items.GetValue<WorkflowFileItem>().LoadedFile);
            }

            // Notify the DebuggerService of the new sourceLocationMapping.
            // When rootInstance == null, it'll just reset the mapping.
            //DebuggerService debuggerService = debuggerService as DebuggerService;
            if (_workflowDesigner.DebugManagerView != null)
            {
                ((DebuggerService)_workflowDesigner.DebugManagerView).UpdateSourceLocations(designerSourceLocationMapping);
            }

            return sourceLocationMapping;
        }

        private object getRootInstance()
        {
            ModelService modelService = this._workflowDesigner.Context.Services.GetService<ModelService>();
            if (modelService != null)
            {
                return modelService.Root.GetCurrentValue();
            }
            else
            {
                return null;
            }
        }

        // Get root WorkflowElement.  Currently only handle when the object is ActivitySchemaType or WorkflowElement.
        // May return null if it does not know how to get the root activity.
        private Activity getRootWorkflowElement(object rootModelObject)
        {
            System.Diagnostics.Debug.Assert(rootModelObject != null, "Cannot pass null as rootModelObject");

            Activity rootWorkflowElement;
            IDebuggableWorkflowTree debuggableWorkflowTree = rootModelObject as IDebuggableWorkflowTree;
            if (debuggableWorkflowTree != null)
            {
                rootWorkflowElement = debuggableWorkflowTree.GetWorkflowRoot();
            }
            else // Loose xaml case.
            {
                rootWorkflowElement = rootModelObject as Activity;
            }
            return rootWorkflowElement;
        }

        private Activity getRootRuntimeWorkflowElement()
        {
            var xaml = this._workflowDesigner.Text;

            Activity root = ActivityXamlServices.Load(_workflowFilePath);
            WorkflowInspectionServices.CacheMetadata(root);

            IEnumerator<Activity> enumerator1 = WorkflowInspectionServices.GetActivities(root).GetEnumerator();
            //Get the first child of the x:class
            enumerator1.MoveNext();
            root = enumerator1.Current;
            return root;
        }

        private Dictionary<object, SourceLocation> refreshSourceLocationMapping(IDesignerDebugView debugView, ModelService modelService)
        {
            var nonPublicInstance = BindingFlags.Instance | BindingFlags.NonPublic;
            var debuggerServiceType = typeof(DebuggerService);
            var ensureMappingMethodName = "EnsureSourceLocationUpdated";
            var mappingFieldName = "instanceToSourceLocationMapping";
            var ensureMappingMethod = debuggerServiceType.GetMethod(ensureMappingMethodName, nonPublicInstance);
            var mappingField = debuggerServiceType.GetField(mappingFieldName, nonPublicInstance);

            if (ensureMappingMethod == null)
                throw new MissingMethodException(debuggerServiceType.FullName, ensureMappingMethodName);
            if (mappingField == null)
                throw new MissingFieldException(debuggerServiceType.FullName, mappingFieldName);

            var rootActivity = modelService.Root.GetCurrentValue() as Activity;
            if (rootActivity != null)
                WorkflowInspectionServices.CacheMetadata(rootActivity);

            ensureMappingMethod.Invoke(debugView, new object[0]);
            var mapping = (Dictionary<object, SourceLocation>)mappingField.GetValue(debugView);

            return mapping;
        }
        #endregion
    }
}
